package fr.unice.polytech.chord.gui.dialogs;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.math.BigInteger;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;

import fr.unice.polytech.chord.core.Entry;
import fr.unice.polytech.chord.core.Key;
import fr.unice.polytech.chord.core.Tracker;
import fr.unice.polytech.chord.gui.ChordVisualizer;
import fr.unice.polytech.chord.gui.components.JLimitedSizeTextField;
import fr.unice.polytech.chord.gui.util.SpringUtilities;

/**
 * Dialogs used in order to add an {@link Entry} on the overlay.
 * 
 * @author Anthony Parisy
 * @author Laurent Pellegrino
 * @author Marc Valdener
 * 
 * @version 06/11/2009
 */
@SuppressWarnings("serial")
public class AddEntryDialog extends ToolBarJDialog implements ActionListener {

	private JTextField keyTextField;
	private JTextField valueTextField;
	private JButton addButton;

	public AddEntryDialog(JFrame parent, JButton toolBarButton) {
		super(parent, "Add Entry", toolBarButton);
	}

	public void createAndShowDialog() {
		super.getContentPane().add(this.createDialog());
		super.pack();
		super.setResizable(false);
		super.setLocationRelativeTo(super.getOwner());
		super.setVisible(true);
	}

	private JPanel createDialog() {
		JPanel container = new JPanel();
		container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
		container.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

		super.addWindowListener(new WindowAdapter() {
			@Override
			public void windowActivated(WindowEvent e) {
				super.windowActivated(e);
				AddEntryDialog.this.keyTextField.requestFocus();
			}

			@Override
			public void windowDeactivated(WindowEvent e) {
				super.windowDeactivated(e);
			}
		});

		JPanel formPanel = new JPanel(new SpringLayout());
		JLabel keyLabel = new JLabel("Key : ");
		JLabel valueLabel = new JLabel("Value : ");

		this.addButton = new JButton("add entry");
		this.addButton.addActionListener(this);
		this.keyTextField = new JLimitedSizeTextField(15, Key.NB_BITS);
		keyLabel.setLabelFor(this.keyTextField);
		valueLabel.setLabelFor(this.valueTextField);
		this.valueTextField = new JTextField(15);
		this.valueTextField.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					AddEntryDialog.this.addButton.doClick();
				}
			}
		});
		this.keyTextField.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					AddEntryDialog.this.addButton.doClick();
				}
			}
		});

		formPanel.add(keyLabel);
		formPanel.add(this.keyTextField);
		formPanel.add(valueLabel);
		formPanel.add(this.valueTextField);
		SpringUtilities.makeCompactGrid(formPanel, 2, 2, 6, 6, 6, 6);

		container.add(formPanel);
		container.add(this.addButton);

		return container;
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		Key key = null;
		String opt = "";

		if (!this.keyTextField.getText().trim().isEmpty()) {
			try {
				key = new Key(Integer.parseInt(this.keyTextField.getText()));
			} catch (Exception e) {
				this.keyTextField.setText("");
				this.keyTextField.requestFocus();
				JOptionPane.showMessageDialog(this,
						"Key must be a positive number", "Add Entry",
						JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			if (new BigInteger(this.keyTextField.getText())
					.compareTo(new BigInteger(""
							+ (int) Math.pow(2, Key.NB_BITS))) >= 0) {
				opt = "\n" + this.keyTextField.getText() + " = " + key
						+ " mod 2^" + Key.NB_BITS;
			}
		} else {
			key = new Key(this.valueTextField.getText());
		}

		Tracker remoteTracker = ((ChordVisualizer) super.getOwner())
				.getTracker();
		if (remoteTracker.getNumberOfPeersManaged() == 0) {
			JOptionPane.showMessageDialog(this,
					"There is no peer on the overlay", "Add Entry",
					JOptionPane.INFORMATION_MESSAGE);
			this.keyTextField.setText("");
			this.valueTextField.setText("");
			super.setVisible(false);
		} else if (this.valueTextField.getText().trim().isEmpty()) {
			this.valueTextField.requestFocus();
			JOptionPane.showMessageDialog(this, "You must specify a value",
					"Add Entry", JOptionPane.INFORMATION_MESSAGE);
		} else if (remoteTracker.getRandomPeer().get(key) != null) {
			JOptionPane
					.showMessageDialog(
							this,
							"The entry with key "
									+ key
									+ " already exists on the overlay\nPlease remove it before to add",
							"Add Entry", JOptionPane.INFORMATION_MESSAGE);
			this.keyTextField.setText("");
			this.valueTextField.setText("");
			super.setVisible(false);
		} else {
			remoteTracker.getRandomPeer().put(
					new Entry<String>(key, this.valueTextField.getText()));

			JOptionPane.showMessageDialog(this, "(" + key + ","
					+ this.valueTextField.getText()
					+ ") has been added on the overlay" + opt, "Add Entry",
					JOptionPane.INFORMATION_MESSAGE);
			this.keyTextField.setText("");
			this.valueTextField.setText("");
			super.setVisible(false);
		}
	}
}
